From 0b3823d5820b250bb9a0da534ef7d3b96354b87b Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 11 Aug 2005 10:34:32 +0000 Subject: [PATCH] PAE page directories must be below 4GB. Based on a patch from Gerd Knorr. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c | 6 ++++++ xen/arch/x86/domain_build.c | 17 ++++++++++------- xen/arch/x86/mm.c | 8 ++++++++ xen/include/asm-x86/page.h | 8 ++------ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c index 79b4c2b79f..fcf97c79e4 100644 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c @@ -25,6 +25,7 @@ #include #include +#include void show_mem(void) { @@ -274,6 +275,11 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused) { unsigned long flags; +#ifdef CONFIG_X86_PAE + /* this gives us a page below 4GB */ + xen_contig_memory((unsigned long)pgd, 0); +#endif + if (!HAVE_SHARED_KERNEL_PMD) spin_lock_irqsave(&pgd_lock, flags); diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index 6e7b022032..9ba5b4512b 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -74,7 +74,7 @@ int construct_dom0(struct domain *d, unsigned long _initrd_start, unsigned long initrd_len, char *cmdline) { - int i, rc, dom0_pae, xen_pae; + int i, rc, dom0_pae, xen_pae, order; unsigned long pfn, mfn; unsigned long nr_pages; unsigned long nr_pt_pages; @@ -143,10 +143,6 @@ int construct_dom0(struct domain *d, nr_pages = avail_domheap_pages() + ((initrd_len + PAGE_SIZE - 1) >> PAGE_SHIFT) + ((image_len + PAGE_SIZE - 1) >> PAGE_SHIFT); - if ( (page = alloc_largest(d, nr_pages)) == NULL ) - panic("Not enough RAM for DOM0 reservation.\n"); - alloc_spfn = page_to_pfn(page); - alloc_epfn = alloc_spfn + d->tot_pages; if ( (rc = parseelfimage(&dsi)) != 0 ) return rc; @@ -215,8 +211,15 @@ int construct_dom0(struct domain *d, #endif } - if ( ((v_end - dsi.v_start) >> PAGE_SHIFT) > (alloc_epfn - alloc_spfn) ) - panic("Insufficient contiguous RAM to build kernel image.\n"); + order = get_order(v_end - dsi.v_start); + if ( (1UL << order) > nr_pages ) + panic("Domain 0 allocation is too small for kernel image.\n"); + + /* Allocate from DMA pool: PAE L3 table must be below 4GB boundary. */ + if ( (page = alloc_domheap_pages(d, order, ALLOC_DOM_DMA)) == NULL ) + panic("Not enough RAM for domain 0 allocation.\n"); + alloc_spfn = page_to_pfn(page); + alloc_epfn = alloc_spfn + d->tot_pages; printk("PHYSICAL MEMORY ARRANGEMENT:\n" " Dom0 alloc.: %"PRIphysaddr"->%"PRIphysaddr, diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 34b282b230..827aa23463 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -856,6 +856,14 @@ static int alloc_l3_table(struct pfn_info *page, unsigned long type) ASSERT(!shadow_mode_refcounts(d)); +#ifdef CONFIG_X86_PAE + if ( pfn >= 0x100000 ) + { + MEM_LOG("PAE pgd must be below 4GB (0x%lx >= 0x100000)", pfn); + return 0; + } +#endif + pl3e = map_domain_page(pfn); for ( i = 0; i < L3_PAGETABLE_ENTRIES; i++ ) { diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 0ac2ab42b0..71edad1530 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -283,13 +283,9 @@ extern void paging_init(void); static __inline__ int get_order(unsigned long size) { int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { + size = (size-1) >> PAGE_SHIFT; + for ( order = 0; size; order++ ) size >>= 1; - order++; - } while (size); return order; } -- 2.30.2